/*
 * For legal stuff see the file COPYRIGHT
 */
#import "ClientInspector.h"
#import "ClientViewMgr.h"

/* Indices of the slots in the form */
typedef enum {
  ClientSlot,
  ShortNameSlot,
  StreetSlot,
  CitySlot,
  StateSlot,
  ZipSlot,
  ContactSlot,
  EmailSlot,
  FaxSlot,
  RateSlot
} FormField;

@interface ClientViewMgr(PRIVATE)
- showInfo:(ClientInfo *)info inspector:(ClientInspector *)inspector;
- (void)loadFromForm:(ClientInfo *)info;
- clearForm;
- setIsEditing:(BOOL)flag;
@end

@implementation ClientViewMgr

- awakeFromNib
{
  [dataForm setTextDelegate:self];
  return self;
}

- mgrShow:(ClientInspector *)inspector
{
  [self showInfo:[inspector selectedClient] inspector:inspector];
  return self;
}

/*
 * This view ignores double clicks from the main client browser.
 */
- (BOOL)mgrDoubleClick:(ClientInspector *)inspector
{
  return NO;
}

/*
 * Create a new ClientInfo object and copy the data from the form.
 */
- (BOOL)mgrAdd:(ClientInspector *)inspector
{
  ClientInfo *info = [[ClientInfo alloc] init];

  [self loadFromForm:info];
  [inspector addClient:info];
  [self showInfo:info inspector:inspector];
  return YES;
}

/*
 * Delete the ClientInfo object from the list.
 */
- (BOOL)mgrDelete:(ClientInspector *)inspector
{
  ClientInfo *info;

  if ( NXRunAlertPanel( [NXApp appName], "Delete client `%s'?",
		   "Yeah. Who needs 'em", "Perhaps not", NULL,
		       [[inspector selectedClient] shortName] ) != NX_ALERTDEFAULT ) {
    return NO;
  }

  info = [inspector deleteSelectedClient];
  [self saveDeletedItem:info];
  [self showInfo:[inspector selectedClient] inspector:inspector];
  return YES;
}

- (BOOL)mgrUndelete:(ClientInspector *)inspector
{
  ClientInfo *info = [self getDeletedItem];

  if ( info ) {
    [inspector addClient:info];
    [self showInfo:info inspector:inspector];
    return YES;
  }

  NXBeep();
  return NO;			/* indicate that no save is required */
}

/*
 * Modify the ClientInfo object for the currently selected client.
 */
- (BOOL)mgrModify:(ClientInspector *)inspector
{
  ClientInfo *info = [inspector selectedClient];

  [self loadFromForm:info];
  [inspector decacheBrowser];
  [[NXApp delegate] decacheBrowser];
  [self showInfo:info inspector:inspector];
  return YES;
}

- (BOOL)canAdd
{
  return enteringNewClient;
}

- (BOOL)canModify
{
  return hasSelection && isEditing;
}

- (BOOL)canDelete
{
  return hasSelection;
}

- (BOOL)isEditing
{
  return isEditing;
}


@implementation ClientViewMgr(PRIVATE)

- showInfo:(ClientInfo *)info inspector:(ClientInspector *)inspector
{
  if ( info == nil ) {
    [self clearForm];
  } else {
    [dataForm setStringValue:[info contactName] at:ContactSlot];
    [dataForm setStringValue:[info clientName]  at:ClientSlot];
    [dataForm setStringValue:[info shortName]   at:ShortNameSlot];
    [dataForm setStringValue:[info street]      at:StreetSlot];
    [dataForm setStringValue:[info city]        at:CitySlot];
    [dataForm setStringValue:[info addrState]   at:StateSlot];
    [dataForm setStringValue:[info zipCode]     at:ZipSlot];
    [dataForm setStringValue:[info emailAddr]   at:EmailSlot];
    [dataForm setStringValue:[info faxNumber]   at:FaxSlot];
    [dataForm setFloatValue: [info hourlyRate]  at:RateSlot];
    hasSelection = YES;
  }
  [dataForm selectTextAt:ClientSlot];
  [self setIsEditing:NO];
  return self;
}

/*
 * Copy data from the form into the given ClientInfo object
 */
- (void)loadFromForm:(ClientInfo *)info
{
  [info setContactName: [dataForm stringValueAt:ContactSlot]];
  [info setClientName:  [dataForm stringValueAt:ClientSlot]];
  [info setShortName:   [dataForm stringValueAt:ShortNameSlot]];
  [info setStreet:      [dataForm stringValueAt:StreetSlot]];
  [info setCity:        [dataForm stringValueAt:CitySlot]];
  [info setAddrState:   [dataForm stringValueAt:StateSlot]];
  [info setZipCode:     [dataForm stringValueAt:ZipSlot]];
  [info setEmailAddr:   [dataForm stringValueAt:EmailSlot]];
  [info setFaxNumber:   [dataForm stringValueAt:FaxSlot]];
  [info setHourlyRate:  [dataForm floatValueAt:RateSlot]];
}

- clearForm
{
  [dataForm setStringValue:"" at:ContactSlot];
  [dataForm setStringValue:"" at:ClientSlot];
  [dataForm setStringValue:"" at:ShortNameSlot];
  [dataForm setStringValue:"" at:StreetSlot];
  [dataForm setStringValue:"" at:CitySlot];
  [dataForm setStringValue:"" at:StateSlot];
  [dataForm setStringValue:"" at:ZipSlot];
  [dataForm setStringValue:"" at:EmailSlot];
  [dataForm setStringValue:"" at:FaxSlot];
  [dataForm setStringValue:"" at:RateSlot];

  [dataForm selectTextAt:ContactSlot];
  hasSelection = NO;
  return self;
}

- setIsEditing:(BOOL)flag
{
  isEditing = flag;

  if ( isEditing == NO )
    enteringNewClient = NO;	/* can't be entering a new one if not editing! */
    
  [[ClientInspector sharedInstance] setDocEdited:flag];
  return self;
}

/*
 * Delegated from Form. If the user starts typing over an existing
 * entry, enable the Update and Cancel buttons. Disable delete too,
 * forcing the user to use the delete button only after selecting
 * an entry.
 */
- textDidChange:textObj
{
  if ( enteringNewClient == NO && [dataForm selectedIndex] == ClientSlot ) {
    enteringNewClient = YES;
    [self setIsEditing:YES];
  } else if ( isEditing == NO )
    [self setIsEditing:YES];
  else
    return self;		/* do nothing */

  [ClientInspector updateButtons];
  return self;
}

/*
 * Allow pasting in of client data
 */
- paste:sender
{
  id pb=[Pasteboard newName:NXGeneralPboard];
  const char *pTypes[2] = { NXAsciiPboardType, NULL};
	
  if ( [pb findAvailableTypeFrom:pTypes num:1] ) {
    NXStream *stream;
    int cols, rows, i, r;
    char line[1024];
		
    stream=[pb readTypeToStream:NXAsciiPboardType];
		
    r=0;
    [dataForm getNumRows:&rows numCols:&cols];
    for (i=0; i < rows && r != EOF; i++) {
      r=NXScanf(stream, "%[^\n\000]", line);
      [dataForm setStringValue:line at:i];
      if (r != EOF ) {
	r=NXGetc(stream);
	r=NXGetc(stream);
	if (r != EOF ) NXUngetc(stream);
      }
    }
    NXCloseMemory(stream, NX_FREEBUFFER);
    [ClientInspector updateButtons];
			
    return self;
  }

  return nil;
}

@end
